package com.waitingsnow.common.share.bridia.net
{
	import com.waitingsnow.common.share.bridia.utils.BDStringUtils;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	
	/**
	 * 请求完成时触发该事件,访问BDHttpLoader.data获取服务器端返回的数据.
	 */	
	
	[Event(name="complete", type="flash.events.Event")]
	
	/**
	 * 请求错误时抛出该事件.
	 */	
	
	[Event(name="ioError", type="flash.events.IOErrorEvent")]
	
	/**
	 * 每次请求接口时都会抛出该事件.
	 */	
	
	[Event(name="httpStatus", type="flash.events.HTTPStatusEvent")]
	
	/**
	 * 跨域请求发生安全错误时抛出该事件. 
	 */	
	
	[Event(name="securityError", type="flash.events.SecurityErrorEvent")]

	/**
	 *  
	 * @author <a href="http://www.bridia.com">Bridia.com</a> : Tensharp
	 * 
	 * <p>使用multipart/form-data来传递参数并上传文件(使用URLLoader上传).</p>
	 * <pre>
	 * 		var loader:BDHttpLoader = new BDHttpLoader ();
	 *		loader.addParameters ("pic", picName, picData);
	 *		loader.connect (request);
	 * </pre>
	 */	
	
	public class BDHttpLoader extends EventDispatcher
	{
		///
		///	[Content type]
		///
		
		private var _contentType:String = "multipart/form-data";
		
		/**
		 * 
		 * <p>设置URLRequest的contentType</p>
		 *  
		 * @return 
		 * 
		 */		

		public function get contentType():String
		{
			return _contentType;
		}
		
		///	[setter]

		public function set contentType(value:String):void
		{
			_contentType = value;
		}
		
		///
		///	[Method]
		///
		
		private var _method:String = "POST";
		
		/**
		 * 
		 * <p>设置请求方式.</p> 
		 * 
		 * @return 
		 * 
		 */		

		public function get method():String
		{
			return _method.toUpperCase ();
		}
		
		///	[setter]

		public function set method(value:String):void
		{
			_method = value;
		}
		
		///
		///	[url]
		///
		
		private var _url:String;

		/**
		 * 
		 * <p>需要请求的url</p>
		 *  
		 * @return 
		 * 
		 */		
		
		public function get url():String
		{
			return _url;
		}

		///	[setter]
		
		public function set url(value:String):void
		{
			_url = value;
		}
		
		///
		///	[Data]
		///
		
		/**
		 *
		 * <p>请求完成后服务器端返回的数据.</p>
		 *  
		 * @return 
		 * 
		 */		
		
		public function get data ():Object
		{
			if (!loader)
			{
				return null;
			}

			return loader.data;
		}
		
		//
		
		///
		///	[ByteArray]
		///
		
		/**
		 * @private 
		 */		
		
		private var source:ByteArray;
		
		///
		///	[URLLoader]
		///
		
		/**
		 * @private 
		 */		
		
		private var loader:URLLoader;
		
		///
		///	[Parameter]
		///
		
		/**
		 * @private
		 * 
		 * 存储参数 
		 */		
		
		private var parameter:Object;
		
		///
		///	[Constructor]
		///
		
		/**
		 *
		 * <p>创建一个新的BDHttpLoader.</p> 
		 * 
		 */		
		
		public function BDHttpLoader ()
		{
			initialize ();
		}
		
		///
		///	[initialize]
		///
		
		/**
		 *
		 * @private
		 * 
		 * <p>初始化方法.</p> 
		 * 
		 */		
		
		private function initialize ():void
		{
			source    = new ByteArray ();
			parameter = {};
		}
		
		///
		///	[connect]
		///
		
		/**
		 * <p>将数据写入二进制流并请求服务器端.</p>
		 * <p>如果request为空会创建一个新的URLRequest对象并写入数据.</p>
		 * 
		 * @param request 包含了URL以及header信息的URLRequest
		 * 
		 */		
		
		public function connect (request:URLRequest = null):void
		{
			if (!request)
			{
				request = new URLRequest ();
			}
			
			//
			
			var bound:String = bound ();
			
			//
			
			var disposition:String;
			var contentType:String = "Content-Type: " + this.contentType;
			
			//
			
			for (var i:String in parameter)
			{
				if (!parameter[i].data)
				{
					disposition = 'Content-Disposition: form-data; name="' + i + '"';
					
					source.writeMultiByte("--" + bound + "\r\n","UTF-8"); 
					source.writeMultiByte(disposition + "\r\n\r\n", "UTF-8"); 
					source.writeMultiByte(parameter[i].value + "\r\n","UTF-8"); 
				}
				else
				{
					disposition = 'Content-Disposition: form-data; name="' + i + '"' + '; filename="' + parameter[i].value + '"';
					
					source.writeMultiByte ("--" + bound + "\r\n","UTF-8");
					source.writeMultiByte (disposition + "\r\n", "UTF-8");
					source.writeMultiByte (contentType + "\r\n\r\n","UTF-8"); 
					source.writeBytes (parameter[i].data, 0, parameter[i].data.length); 
					source.writeMultiByte ("\r\n", "UTF-8"); 
				}
			}
			
			//
			
			source.writeMultiByte ("--" + bound + "--", "UTF-8");
			
			//
			
			if (url && url.length > 0)
			{
				request.url = url;
			}
			
			//
			
			request.method      = method;
			request.contentType = this.contentType + "; boundary=" + bound;
			request.data        = source;
			
			//
			
			loader = new URLLoader (request);
			
			loader.addEventListener (Event.COMPLETE, loadCompleteHandler);
			loader.addEventListener (IOErrorEvent.IO_ERROR, loadErrorHandler);
			loader.addEventListener (HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
			loader.addEventListener (SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
		}
		
		///
		///	[Add parameters]
		///
		
		/**
		 * <p>添加一个参数.</p> 
		 * 
		 * @param name 参数名
		 * @param value 参数值
		 * @param data 二进制文件流
		 * 
		 */		
		
		public function addParameters (name:String, value:String, data:ByteArray = null):void
		{
			if (!parameter)
			{
				parameter = {};
			}
			
			//
			
			if (!parameter[name])
			{
				parameter[name] = new BDHttpParamters (name, value, data);
			}
			else
			{
				parameter[name].value = value;
				parameter[name].data  = data;
			}
		}
		
		///
		///	[Get parameters]
		///
		
		/**
		 * 
		 * <p>获取一个参数.</p> 
		 * 
		 * @param name 参数名
		 * @return 返回一个BDHttpParameters对象.
		 * 
		 */		
		
		public function getParamters (name:String):BDHttpParamters
		{
			if (!parameter)
			{
				return null;
			}
			
			return parameter[name];
		}
		
		///
		///	[Remove parameters]
		///
		
		/**
		 * 
		 * <p>删除一个参数</p> 
		 * 
		 * @param name 参数名
		 * 
		 */		
		
		public function removeParamters (name:String):void
		{
			if (!parameter)
			{
				return;
			}
			
			//
			
			delete parameter[name];
		}
		
		///
		///	[Bound]
		///
		
		/**
		 * @private
		 * 
		 * <p>生成分隔线</p>
		 *  
		 * @return 
		 * 
		 */		
		
		private function bound ():String
		{
			return "---------------------------" + BDStringUtils.generateCheckCode (13).toLowerCase ();
		}
		
		
		//
		
		///
		///	[Load complete handler]
		///
		
		/**
		 *
		 * @private
		 * 
		 * <p>加载完成事件</p>
		 *  
		 * @param event
		 * 
		 */		
		
		private function loadCompleteHandler (event:Event):void
		{
			dispatchEvent (new Event (event.type, event.bubbles, event.cancelable));
		}
		
		///
		///	[Load error handler]
		///
		
		/**
		 * @private 
		 * 
		 * <p>错误事件</p>
		 *  
		 * @param event
		 * 
		 */		
		
		private function loadErrorHandler (event:IOErrorEvent):void
		{
			dispatchEvent (new IOErrorEvent (event.type, event.bubbles, event.cancelable, event.text));
		}
		
		///
		///	[Http status handler]
		///
		
		/**
		 * @private
		 * 
		 * <p>http status event.</p>
		 * 
		 * @param event
		 * 
		 */		
		
		private function httpStatusHandler (event:HTTPStatusEvent):void
		{
			dispatchEvent (new HTTPStatusEvent (event.type, event.bubbles, event.cancelable, event.status));
		}
		
		///
		///	[Security error handler]
		///
		
		/**
		 * @private
		 * 
		 * <p>Security error handler</p>
		 *  
		 * @param event
		 * 
		 */		
		
		private function securityErrorHandler (event:SecurityErrorEvent):void
		{
			dispatchEvent (new SecurityErrorEvent (event.type, event.bubbles, event.cancelable, event.text));
		}
	}
}